package com.qiuling.iot.shiro;

import com.qiuling.iot.constants.Constant;
import com.qiuling.iot.service.PermissionService;
import com.qiuling.iot.service.RoleService;
import com.qiuling.iot.utils.JwtTokenUtil;
import com.qiuling.iot.utils.RedisUtils;
import io.jsonwebtoken.Claims;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @Author：zhangqiang
 * @Description：
 * @Date：Created in 1:52 2020/2/10
 * @Modified By：
 */
public class CustomRealm extends AuthorizingRealm {

    @Autowired
    private RoleService roleService;
    @Autowired
    private PermissionService permissionService;
    @Autowired
    private RedisUtils redisUtils;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof CustomUsernamePasswordToken;
    }

    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String accessToken = (String) principalCollection.getPrimaryPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        String userId = JwtTokenUtil.getUserId(accessToken);
        /**
         * 通过剩余的过期时间比较如果token的剩余过期时间大与标记key的剩余过期时间
         * 就说明这个tokne是在这个标记key之后生成的
         */
        if (redisUtils.hasKey(Constant.JWT_REFRESH_KEY + userId) &&
                redisUtils.getExpire(Constant.JWT_REFRESH_KEY + userId, TimeUnit.MILLISECONDS)
                        > JwtTokenUtil.getRemainingTime(accessToken)) {
            List<String> roleNames = roleService.getRoleNames(userId);
            if (roleNames != null && !roleNames.isEmpty()) {
                info.addRoles(roleNames);
            }
            Set<String> permissions = permissionService.getPermissionsByUserId(userId);
            if (permissions != null) {
                info.addStringPermissions(permissions);
            }

        } else {
            Claims claims = JwtTokenUtil.getClaimsFromToken(accessToken);
            /**
             * 返回该用户的角色信息给授权期
             */
            if (claims.get(Constant.JWT_ROLES_KEY) != null) {
                info.addRoles((Collection<String>) claims.get(Constant.JWT_ROLES_KEY));
            }

            /**
             * 返回该用户的权限信息给授权器
             */
            if (claims.get(Constant.JWT_PERMISSIONS_KEY) != null) {
                info.addStringPermissions((Collection<String>) claims.get(Constant.JWT_PERMISSIONS_KEY));
            }
        }

        return info;
    }

    /**
     * 登录认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
            throws AuthenticationException {
        CustomUsernamePasswordToken customUsernamePasswordToken = (CustomUsernamePasswordToken) authenticationToken;
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(customUsernamePasswordToken.getPrincipal(),
                customUsernamePasswordToken.getCredentials(), CustomRealm.class.getName());
        return info;
    }
}
